<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数式编程</title>
</head>

<body>
  <script>
    //1. 使用函数处理数组

    // 非函数式风格的代码
    // let data = [1, 1, 3, 5, 5]
    // // 计算平均值
    // let total = 0;
    // for (let i = 0; i < data.length; i++) total += data[i];
    // let mean = total / data.length
    // // 计算方差
    // total = 0;
    // for (let i = 0; i < data.length; i++) {
    //   let deviation = data[i] - mean
    //   total += deviation * deviation
    // }
    // let variance = total / (data.length - 1)
    // // 计算标准差
    // let stddev = Math.sqrt(variance)
    // console.log(stddev);

    // 以上计算可以用简洁的函数式风格实现
    // 首先，定义两个简单的函数
    // const sum = (x, y) => x + y
    // const square = x => x * x
    // let data = [1, 1, 3, 5, 5]
    // // 平均数
    // let mean = data.reduce(sum) / data.length
    // let deviation = data.map(x => x - mean)
    // // 标准差
    // let stddev = Math.sqrt(deviation.map(square).reduce(sum) / (data.length - 1))
    // console.log(stddev);

    // 以上的计算我们还可以定义map（）和reduce（）方法的函数版
    // const map = function (a, ...args) { return a.map(...args) }
    // const reduce = function (a, ...args) { return a.reduce(...args) }
    // const sum = (x, y) => x + y
    // const square = x => x * x
    // let data = [1, 1, 3, 5, 5]
    // let mean = reduce(data, sum) / data.length
    // let deviation = map(data, x => x - mean)
    // let stddev = Math.sqrt(reduce(map(deviation, square), sum) / (data.length - 1))
    // console.log(stddev);

    // 2.高阶函数
    // 第一种
    // function not(f) {
    //   return function (...args) {
    //     console.log(this);
    //     let result = f.apply(this, args);
    //     return result;
    //   }
    // }
    // const even = x => x % 2 === 0
    // const odd = not(even)
    // console.log([2, 4, 6].every(odd));

    // 第二种
    // const map = function (a, ...args) { return a.map(...args) }
    // function mapper(f) {
    //   return a => map(a, f)
    // }
    // const increment = x => x + 1;
    // const incrementAll = mapper(increment)
    // console.log(incrementAll([1, 2, 3]));

    // 第三种 更通用的例子
    // function compose(f, g) {
    //   return function (...args) {
    //     return f.call(this, g.apply(this, args))
    //   }
    // }
    // const sum = (x, y) => x + y
    // const square = x => x * x
    // console.log(compose(square, sum)(3, 9));


    // 3.函数的部分应用
    // const f = function (x, y, z) { return x * (y - z) }
    // const sum = (x, y) => x + y
    // const square = x => x * x
    // function compose(f, g) {
    //   return function (...args) {
    //     return f.call(this, g.apply(this, args))
    //   }
    // }
    // const even = x => x % 2 === 0
    // // 传给这个函数的参数回传到左侧
    // function partialLeft(f, ...outerArgs) {
    //   return function (...innerArgs) {
    //     let args = [...outerArgs, ...innerArgs]
    //     // console.log(args);
    //     return f.apply(this, args)
    //   }
    // }
    // // console.log(partialLeft(f, 2)(3, 4));
    // // const increment = partialLeft(sum, 1)
    // // console.log(increment(26));
    // const not = partialLeft(compose, x => !x)
    // const isNumber = not(isNaN)
    // const odd = not(even)
    // console.log(isNumber(2));
    // console.log(odd(3));
    // console.log(odd(3) && isNumber(2));

    // // 传给这个函数的参数回传到右侧
    // function partialRight(f, ...outerArgs) {
    //   return function (...innerArgs) {
    //     let args = [...innerArgs, ...outerArgs]
    //     return f.apply(this, args)
    //   }
    // }
    // // console.log(partialRight(f, 2)(3, 4));
    // const cuberoot = partialRight(Math.pow, 1 / 3)
    // console.log(cuberoot(increment(26)));

    // 这个函数的参数列表作为一个模板。这个参数列表中的undefined值
    // 会被来自内部参数列表的值填充
    // function partial(f, ...outerArgs) {
    //   return function (...innerArgs) {
    //     let args = [...outerArgs];
    //     // console.log(args);
    //     let innerIndex = 0;
    //     for (let i = 0; i < args.length; i++) {
    //       // 如果值是undefined就填充内部的参数
    //       if (args[i] === undefined) args[i] = innerArgs[innerIndex++]
    //     }
    //     // 现在把剩余的内部参数都加进来
    //     args.push(...innerArgs.slice(innerIndex))
    //     console.log(args);
    //     return f.apply(this, args)
    //   }
    // }
    // // console.log(partial(f, undefined, 2)(3, 4));
    // // 实现标准差
    // const map = function (a, ...args) { return a.map(...args) }
    // const reduce = function (a, ...args) { return a.reduce(...args) }
    // const product = (x, y) => x * y
    // const sum = (x, y) => x + y
    // const square = x => x * x
    // function compose(f, g) {
    //   return function (...args) {
    //     console.log(...args);
    //     console.log(g.apply(this, args));
    //     return f.call(this, g.apply(this, args))
    //   }
    // }
    // const neg = partial(product, -1)
    // const sqrt = partial(Math.pow, undefined, .5)
    // const reciprocal = partial(Math.pow, undefined, neg(1))
    // let data = [1, 1, 3, 5, 5]
    // let mean = product(reduce(data, sum), reciprocal(data.length))
    // let stddev = sqrt(product(reduce
    //   (// 相当于map((val,index,Array)=>compose(square, partial(sum, neg(mean)))
    //     map(data, compose(square, partial(sum, neg(mean)))), sum),
    //   reciprocal(sum(data.length, neg(1)))))
    // console.log(mean, stddev);


    // 4.函数记忆
    function memoize(f) {
      const cache = new Map()
      console.log(cache);
      return function (...args) {
        let key = args.length + args.join("+");
        console.log(cache.has(key));
        if (cache.has(key)) {
          return cache.get(key)
        } else {
          // console.log(args);
          let result = f.apply(this, args)
          console.log(result);
          cache.set(key, result)
          return result
        }
      }
    }
    function gcd(a, b) {
      if (a < b) {
        [a, b] = [b, a]
      }
      while (b !== 0) {
        [a, b] = [b, a % b]
      }
      return a;
    }
    const gcdmemo = memoize(gcd)
    console.log(gcdmemo(85, 187));
    console.log(gcdmemo(85, 187));//cache.has(key)为true
    //   const factorial = memoize(function (n) {
    //     return (n <= 1) ? 1 : n * factorial(n - 1)
    //   })
    //   console.log(factorial(5));//同时也为4、3、2、1缓存了值
    //   console.log(factorial(2));//cache.has(key)为true



  </script>
</body>

</html>